package com.itheima.health.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.aliyuncs.exceptions.ClientException;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.health.dao.UserDao;
import com.itheima.health.entity.PageResult;
import com.itheima.health.entity.QueryPageBean;
import com.itheima.health.exception.HealthException;
import com.itheima.health.pojo.Menu;
import com.itheima.health.pojo.Role;
import com.itheima.health.pojo.User;
import com.itheima.health.service.UserService;
import com.itheima.health.utils.SMSUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.*;

/**
 * Description: No Description
 * User: Eric
 */
@Service(interfaceClass = UserService.class)
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;
    @Autowired
    private JedisPool jedisPool;

    /**
     * 根据登陆用户名称查询用户权限信息
     * @param username
     * @return
     */
    @Override
    public User findByUsername(String username) {

        return userDao.findByUsername(username);
    }
    //添加用户，开启事务管理
    @Override
    @Transactional
    public void addUser(User user, Integer[]roleIds) {
        //先判断是否存在同名用户
        String username = user.getUsername();
        User byUse = userDao.findWhitUsername(username);
        //取出明文密码
        String mingwen = user.getPassword();
        if (byUse!=null){
            throw new HealthException("用户名已经被使用");
        } else {
            //把密码放入redis，再加密放入mysql，明文密码放入redis，查询时把明文返回
            Jedis reids = jedisPool.getResource();
            reids.set(user.getUsername(),mingwen);
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            String password = encoder.encode(user.getPassword());
            user.setPassword(password);
            user.setStation("0");
            userDao.addUser(user);
            int userId=user.getId();
            if (roleIds!=null){
                for (Integer roleId : roleIds) {
                    userDao.addUserRole(roleId,userId);
                }
            }
        }
        try {
            SMSUtils.sendShortMessage("SMS_190272158",user.getTelephone(),mingwen);
        } catch (ClientException e) {
            e.printStackTrace();
        }
    }

    //通过用户id查询对应的所有角色id
    @Override
    public List<Integer> findRoleIdsByUserId(int userId) {
        return userDao.findRoleIdsByUserId(userId);
    }
    //分页查询
    @Override
    public PageResult<User> findPage(QueryPageBean queryPageBean) {
        //调用分页工具，开启分页查询，参数当前页和每页个数
        PageHelper.startPage(queryPageBean.getCurrentPage(),queryPageBean.getPageSize());
        //判断查询语句是否为空，不为空则拼接百分号，模糊查询
        if (!StringUtils.isEmpty(queryPageBean.getQueryString())){
            queryPageBean.setQueryString("%"+queryPageBean.getQueryString()+"%");
        }
        //查询
        Page<User>page=userDao.findByCondition(queryPageBean.getQueryString());
        return new PageResult<>(page.getTotal(),page.getResult());
    }
    //通过id查询用户
    @Override
    public User findById(int id) {
        //查询用户时，把redis中明文密码取出，回显
        User user = userDao.findById(id);
        Jedis redis = jedisPool.getResource();
        String password=redis.get(user.getUsername());
        if (password==null){
            String username = user.getUsername();
            redis.set(username,"1234");
            password = redis.get(user.getUsername());
        }
        user.setPassword(password);
        return user;
    }
    //通过id删除用户，开启事务管理
    @Override
    @Transactional
    public void deleteUserById(int id) {
        userDao.deleteRoleUser(id);
        userDao.deleteUserById(id);
    }
    //更新用户，开启事务管理
    @Override
    @Transactional
    public void updateUser(User user, Integer[] roleIds) {
        //修改用户时，把密码先存入redis，再加密放入mysql
        Jedis redis = jedisPool.getResource();
        String s = redis.get(user.getUsername());
        redis.set(user.getUsername(),user.getPassword());
        String mingwen = user.getPassword();
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String password = encoder.encode(user.getPassword());
        user.setPassword(password);
        userDao.updateUser(user);
        userDao.deleteRoleUser(user.getId());
        if (null!=roleIds){
            for (Integer roleId : roleIds) {
                userDao.addUserRole(roleId,user.getId());
            }
        }
        //修改密码，就发送短信
        if (mingwen.equals(s)){

        }else {
            try {
                SMSUtils.sendShortMessage("SMS_190272158",user.getTelephone(),mingwen);
            } catch (ClientException e) {
                e.printStackTrace();
            }
        }
    }

    //查询所有用户
    @Override
    public List<User> findUser() {
        return userDao.findUser();
    }
    /**
     * @return com.itheima.health.pojo.User
     * @explain根据用户名查询能访问的菜单
     * @Author cnn
     * @Description findMenusByUsername
     * @Date 10:33 2020/7/6
     * @Param [username]
     */
    @Override
    public Set<Menu> findMenusByUsername(String username) {
        com.itheima.health.pojo.User user = userDao.findMenusByUsername(username);
        // 用户所拥有的角色
        Set<Role> roles = user.getRoles();
        Set<Menu> menus = new HashSet<>();
        if (null != roles) {
            for (Role role : roles) {
                // 角色下所有能访问的菜单
                menus.addAll(role.getMenus());
            }
        }
        return menus;
    }

    /**
     * @return java.util.List<java.lang.String>
     * @explain 根据查询的菜单封装到List集合
     * @Author cnn
     * @Description getMenuByLoadUserAuthority
     * @Date 10:33 2020/7/6
     * @Param [username]
     */
    @Override
    @Transactional
    public List<Menu> getMenuByLoadUserAuthority(String username) {
        Set<Menu> menus = findMenusByUsername(username);
        //父菜单集合
        List<Menu> parentMenus = new ArrayList<>();
        for (Menu parentMenu : menus) {
            //将子菜单排序后存入父菜单
            if (null == parentMenu.getParentMenuId()) {
                List<Menu> childrenMenu = new ArrayList<>();
                List<Integer> childPriority = new ArrayList<>();
                for (Menu menu : menus) {
                    if (parentMenu.getId() == menu.getParentMenuId()) {
                        childrenMenu.add(menu);
                        childPriority.add(menu.getPriority());
                    }
                }
                List<Menu> sortChildMenus = new ArrayList<>();
                Collections.sort(childPriority);
                for (Integer integer : childPriority) {
                    for (Menu menu : childrenMenu) {
                        if (integer == menu.getPriority()){
                            sortChildMenus.add(menu);
                        }
                    }
                }
                //子菜单
                parentMenu.setChildren(sortChildMenus);
                //父菜单
                parentMenus.add(parentMenu);
            }
        }
        //父菜单排序
        List<Menu> sortParentMenus = sortParent(parentMenus);
        return sortParentMenus;
    }
    /** @explain 父菜单排序
     * @Author cnn
     * @Description  sort
     * @Date 11:13 2020/7/6
     * @Param [menus]
     * @return java.util.List<com.itheima.health.pojo.Menu>
     */
    public List<Menu> sortParent(List<Menu> menus){
        List<Integer> menusPriority = new ArrayList<>();
        List<Menu> sortMenu = new ArrayList<>();
        for (Menu menu : menus) {
            if (null == menu.getParentMenuId()) {
                menusPriority.add(menu.getPriority());
            }
        }
        //对优先级进行排序,确定菜单出现的顺序
        Collections.sort(menusPriority);
        for (Integer integer : menusPriority) {
            for (Menu menu : menus) {
                if (integer == menu.getPriority()){
                    sortMenu.add(menu);
                }
            }
        }
        return sortMenu;
    }
}
